package com.mihuo.util;

import com.mihuo.entity.constant.RedisKey;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * JWT工具类 - 用于生成和验证JWT令牌
 *
 * @author mihuo
 * @date 2025-09-27
 * @version 1.1
 */
public class JwtUtil {

    private static final String secretKey = "S1d9mB5k7j2yJNr3Hil6uCtui+cyeQCJvnnOLT8d7CXB7LiuFE9oxEXC8rvU8xmV/rFVf/NGz5St40Cv0/n4LQ==";

    /**
     * 生成JWT Token
     *
     * @param userId 用户ID
     * @param roles 用户角色列表
     * @return JWT令牌字符串
     */
    public static String createToken(String userId, List<String> roles) {
        // 创建Claims映射，用于存储JWT的声明信息
        Map<String, Object> claims = new HashMap<>();
        claims.put("roles", roles);

        Date now = new Date();
        Date validity = new Date(now.getTime() + RedisKey.LOGIN_USER_EXPIRE);

        return Jwts.builder()
                .setClaims(claims) // 设置自定义声明
                .setSubject(userId) // 设置主题（用户ID）
                .setIssuedAt(now) // 设置签发时间
                .setExpiration(validity) // 设置过期时间
                .signWith(SignatureAlgorithm.HS512, secretKey) // 签名算法和密钥
                .compact();
    }

    /**
     * 验证Token的有效性
     *
     * @param token JWT令牌
     * @return true-有效, false-无效
     */
    public static boolean validateToken(String token) {
        try {
            Jwts.parser()
                    .setSigningKey(secretKey)
                    .build()
                    .parseClaimsJws(token);
            return true;
        } catch (JwtException | IllegalArgumentException e) {
            // 记录验证失败的日志（实际项目中建议添加）
            return false;
        }
    }

    /**
     * 从Token中解析Claims（声明信息）
     *
     * @param token JWT令牌
     * @return Claims对象
     * @throws JwtException 当Token无效时抛出异常
     */
    public static Claims parseToken(String token) {
        return Jwts.parser()
                .setSigningKey(secretKey)
                .build()
                .parseClaimsJws(token)
                .getBody();
    }

    /**
     * 从Token中获取用户ID（Subject）
     *
     * @param token JWT令牌
     * @return 用户ID
     */
    public static String getUserIdFromToken(String token) {
        Claims claims = parseToken(token);
        return claims.getSubject();
    }

    /**
     * 从Token中获取用户角色列表
     *
     * @param token JWT令牌
     * @return 角色列表
     */
    @SuppressWarnings("unchecked")
    public static List<String> getRolesFromToken(String token) {
        Claims claims = parseToken(token);
        return (List<String>) claims.get("roles");
    }

    /**
     * 检查Token是否即将过期（在指定时间内过期）
     *
     * @param token JWT令牌
     * @param millis 过期阈值（毫秒）
     * @return true-即将过期, false-未即将过期
     */
    public static boolean isTokenExpiringSoon(String token, long millis) {
        try {
            Claims claims = parseToken(token);
            Date expiration = claims.getExpiration();
            Date now = new Date();
            return (expiration.getTime() - now.getTime()) <= millis;
        } catch (JwtException e) {
            return true; // 如果解析失败，视为需要刷新
        }
    }
}